package cmd

import (
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

func init() {
	// 获取日志文件句柄
	// 以 只写入文件|没有时创建|文件尾部追加 的形式打开这个文件
	logFile, err := os.OpenFile(`./logs.log`, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_TRUNC, 0666)
	if err != nil {
		fmt.Println("读取日志文件错误!")
		os.Exit(1)
	}

	// 设置存储位置
	log.SetOutput(logFile)
}

func Run() {
	fmt.Println("开始运行!!!")
	log.Println("开始运行!!!")
	FileName := "portForward.conf"
	//FileName := "C:\\Users\\Erin\\Desktop\\portForward.conf"
	fi, err := os.ReadFile(FileName)
	if err != nil {
		fmt.Printf("读取文件错误:"+FileName+",错误为:%v\n", err)
		log.Fatalln("读取配置文件错误:" + err.Error())
	}
	split := strings.Split(string(fi), "\n")
	var fromportLis, toportList []string
	for _, val := range split {
		if !strings.Contains(val, "#") && val != "" {
			confIp := strings.Split(val, " ")
			fromportLis = append(fromportLis, confIp[0])
			toportList = append(toportList, confIp[1])
		}
	}
	fmt.Println("开始转发!!!")
	log.Println("开始转发!!!")
	go (func() {
		// 每一个转发规则,开启一个协程去处理
		for i, val := range fromportLis {
			fmt.Println(val, "---->", toportList[i])
			log.Println(val, "---->", toportList[i])
			go forward(val, toportList[i])
		}
	})()
	for {
		time.Sleep(5 * time.Minute)
		//fmt.Println(time.Now())
	}
}

func forward(fromaddr, toaddr string) {
	//源端口，目的端口
	// 开始连接 fromaddr 监听地址, 创建监听器
	fromlistener, err := net.Listen("tcp", fromaddr)
	if err != nil {
		fmt.Println("无法监听:" + fromaddr + ",错误:" + err.Error())
		log.Println("无法监听:" + fromaddr + ",错误:" + err.Error())
	}
	defer fromlistener.Close()
	// 循环处理连接的请求
	for {
		// 接收监听器,监听到的连接请求对象
		fromcon, err := fromlistener.Accept()
		if err != nil {
			log.Println("无法接受请求,错误:" + err.Error())
		} else {
			log.Println("新连接: " + fromaddr + " ----> " + toaddr + " 详情: " + fromcon.RemoteAddr().String())
		}
		go handle(fromcon, toaddr)
	}
}
func handle(sconn net.Conn, rip string) {
	defer sconn.Close()
	// 连接目标ip地址
	dconn, err := net.Dial("tcp", rip)
	if err != nil {
		fmt.Println("连接错误:" + rip + ",错误:" + err.Error())
		// 不要使用fatalln 方法,否则会触发主进程退出!
		//log.Fatalln
		log.Println("连接错误:" + rip + ",错误:" + err.Error())
		return
	}
	ExitChan1 := make(chan bool)
	ExitChan2 := make(chan bool)
	// 端口互换数据
	go func(sconn net.Conn, dconn net.Conn, Exit chan bool) {
		// 转发数据
		io.Copy(dconn, sconn)
		ExitChan1 <- true
		close(ExitChan1)
	}(sconn, dconn, ExitChan1)
	go func(sconn net.Conn, dconn net.Conn, Exit chan bool) {
		io.Copy(sconn, dconn)
		ExitChan2 <- true
		close(ExitChan2)
	}(sconn, dconn, ExitChan2)
	// 等待端口间数据交换完成
	<-ExitChan1
	<-ExitChan2
	dconn.Close()
}
